#include "ObjectPool.h"
template <class T>
class ObjectPool
{
public:
    // 申请内存的函数，参数为空，返回值是T*
    T *New()
    {
        // 创建一个T*类型的obj变量，将其赋值为nullptr
        // obj的作用就是作为申请到的内存块返回
        T *obj = nullptr;
        // 优先把还回来的内存块，再次重复利用
        // 如果存在还回来的内存块
        if (_freeList)
        {
            // 设定一个void*的next指针
            // next的作用是指向头指针的下一个节点
            // 以便修改_freeList头指针
            void *next = NextObj(_freeList);
            // 把头指针内存块强转类型，赋值给obj
            obj = (T *)_freeList;
            // 让头指针指向下一个内存块
            _freeList = next;
        }
        // 如果不存在还回来的内存块
        else
        {
            // 如果定长内存的剩余大小连一个对象都申请不了,则重新开一块大空间
            if (_remainBytes < sizeof(T))
            {
                // 把定长内存的剩余字节赋值为128*1024
                _remainBytes = 128 * 1024;
                // 把_memory重新指向新申请的空间
                _memory = (char *)malloc(_remainBytes);
                // 如果内存申请失败了
                if (_memory == nullptr)
                {
                    // 抛出异常
                    throw bad_alloc();
                }
            }
            // 从_memory拿出sizeof(T)大小的内存给obj
            obj = (T *)_memory;
            size_t objSize = sizeof(T) < sizeof(void *) ? sizeof(void *) : sizeof(T); // 计算obj的大小
                                                                                      // 如果要申请的类型大小T，连一个指针的大小（void*）都没有
                                                                                      // 把objSize赋值一个指针大小，方便对齐
                                                                                      // 如果T比一个指针大，要多少就给多少
            _memory += sizeof(T);                                                     // 定长大内存地址指针加上T大小，指向下一个内存段
            _remainBytes -= sizeof(T);                                                // 剩余内存减去T大小
        }
        new (obj) T; // 定位new，调用T的构造函数
        return obj;  // 返回申请到的内存obj的地址
    }

    void Delete(T *obj)
    {
        // 显示调用析构函数清理对象
        obj->~T();
        // 头插
        NextObj(obj) = _freeList;
        _freeList = obj;
    }

private:
    // 定长内存池申请大内存的地方
    char *_memory = nullptr;
    // 定长内存池的剩余空间
    size_t _remainBytes = 0;
    // 定长内存池回收来的内存块就放_freeList中，是个链表
    void *_freeList = nullptr;
};